home *** CD-ROM | disk | FTP | other *** search
/ InfoMagic Internet Tools 1993 July / Internet Tools.iso / RockRidge / mail / mmdf / mmdf-IIb.43 / src / smtp / smtpd.v7.c < prev    next >
Encoding:
C/C++ Source or Header  |  1990-02-28  |  4.2 KB  |  200 lines

  1. /*
  2.  *        S M T P D . C
  3.  *
  4.  *    For 4.1a style networking on a PDP-11.
  5.  */
  6.  
  7. #include <stdio.h>
  8. #include <signal.h>
  9. #include "util.h"
  10. #include <NET/longid.h>
  11. #include <NET/net_types.h>
  12. #include <NET/socket.h>
  13. #include <NET/in.h>
  14.  
  15. extern    int errno;
  16.  
  17. struct sockaddr_in addr = { AF_INET };
  18. struct sockaddr_in rmtaddr;    
  19.  
  20. char    *Smtpserver;        /* Actual smtp server process, full path */
  21. char    *Channel;
  22. int    Maxconnections = 4;    /* Maximum simultaneous connections */
  23. int    numconnections = 0;    /* Number of currently active connections */
  24. int    debug = 0;        /* If nonzero, give verbose output on stderr */
  25. #define    logx    if (debug) log
  26. char    errbuf[BUFSIZ];        /* Logging will be line buffered */
  27. char    programid[40];        /* identification string for log entries */
  28.  
  29. main (argc, argv)
  30. int    argc;
  31. char    **argv;
  32. {
  33.     register int    skt;
  34.     int    pid;
  35.     int    i;
  36.     int    alarmtrap();
  37.     char    *them;
  38.     char    thishost[32];
  39.     char    workarea[32];
  40.  
  41.     setbuf( stderr, errbuf );
  42.     sprintf( programid, "smtpd(%5.5d): ", getpid());
  43.     gethostname( thishost, sizeof(thishost));    /* current hostname */
  44.  
  45.     /* Parse args; args will override configuration file... */
  46.     arginit( argc, argv );
  47.  
  48.     /* Alarms will be used to avoid getting trapped in a wait call */
  49.     signal( SIGALRM, &alarmtrap );
  50.  
  51.     while (1)
  52.     {
  53.         /*
  54.          *  Create a socket to accept a SMTP connection on.
  55.          *  The doloop is due to some sort of IPC bug in 4.1a.
  56.          */
  57.         logx("opening socket...");
  58.         i = 60;
  59.         addr.sin_port = htons(IPPORT_SMTP);   /* swap bytes */
  60.         do{
  61.             skt = socket( SOCK_STREAM, 0, &addr,
  62.                       SO_ACCEPTCONN | SO_KEEPALIVE );
  63.             logx("socket returned %d", skt);
  64.             if( skt < 0 )
  65.                 sleep( 5 );
  66.         } while( skt < 0 && i-- > 0 );
  67.         if( skt < 0 ) {
  68.             log("can't open socket (errno %d)",errno);
  69.             continue;
  70.         }
  71.         logx("socket open on %d", skt );
  72.  
  73.         /*
  74.          *  Accept a connection.
  75.          */
  76.         if( accept( skt, &rmtaddr )) {
  77.             logx("accept error (%d)", errno);
  78.             close( skt );
  79.             sleep(1);
  80.             continue;
  81.         }
  82.  
  83.         if(( pid = fork()) < 0 ) {
  84.             log("could not fork (%d)", errno);
  85.             close( skt );
  86.         } else if( pid == 0 ) {
  87.             /*
  88.              *  Child
  89.              */
  90.             them = raddr( rmtaddr.sin_addr );
  91.             if( them == (-1) )  {
  92.                 /* This should produce a dotted quad */
  93.                 sprintf( workarea, "%u.%u.%u.%u",
  94.                     rmtaddr.sin_addr.s_net&0xff,
  95.                     rmtaddr.sin_addr.s_host&0xff,
  96.                     rmtaddr.sin_addr.s_lh&0xff,
  97.                     rmtaddr.sin_addr.s_impno&0xff);
  98.                 them = &workarea[0];
  99.             }
  100.             log("%s started", them);
  101.  
  102.             dup2( skt, 0 );
  103.             dup2( skt, 1 );
  104.             if( skt > 1 )
  105.                 close( skt );
  106.             execl (Smtpserver, "smtpsrvr", them,
  107.                     thishost, Channel, (char *)0);
  108.             log("server exec error (%d)", errno);
  109.             exit (99);
  110.         }
  111.  
  112.         /*
  113.          *  Parent
  114.          */
  115.         close( skt );
  116.         numconnections++;
  117.  
  118.         /*
  119.          *  This code collects ZOMBIES and implements load
  120.          *  limiting by staying in the do loop while the
  121.          *  Maxconnections active.
  122.          */
  123.         if( numconnections > 1 || Maxconnections == 1 )
  124.             do {
  125.                 alarm( 2 );
  126.                 if( wait( &i ) > 0 )
  127.                     numconnections--;
  128.                 alarm( 0 );
  129.             } while( numconnections >= Maxconnections );
  130.     }
  131. }
  132.  
  133. alarmtrap() {
  134.     signal( SIGALRM, &alarmtrap );
  135.     return;
  136. }
  137.  
  138. arginit( argc, argv )
  139. int    argc;
  140. char    **argv;
  141. {
  142.     register    int    ch;
  143.  
  144.     while ((ch = getopt(argc, argv, "dn:")) != EOF) {
  145.         switch (ch) {
  146.         case 'd':
  147.             debug++;
  148.             break;
  149.  
  150.         case 'n':
  151.             Maxconnections = atoi(optarg);
  152.             if (Maxconnections <= 0) {
  153.                 log("Bad number of connections '%s'", optarg);
  154.                 exit(99);
  155.             }
  156.             log("Maxconnection now %d", Maxconnections);
  157.             break;
  158.  
  159.         default:
  160.             log("Usage: smtpd [-d] [-n #connections] smtpserver channel");
  161.             exit(1);
  162.             break;
  163.         }
  164.     }
  165.  
  166.     if (optind == argc) {
  167.         log("Smtpserver program not specified!");
  168.         log("Usage: smtpd [-d] [-n #connections] smtpserver channel");
  169.         exit(1);
  170.     }
  171.  
  172.     if (optind < argc) {
  173.         if (access(argv[optind], 01) < 0) {    /* execute privs? */
  174.             log("Cannot access server program '%s'", argv[optind]);
  175.             exit(99);
  176.         }
  177.         Smtpserver = argv[optind];
  178.         logx("server is '%s'", Smtpserver);
  179.     }
  180.  
  181.     if (++optind < argc) {
  182.         Channel = argv[optind];
  183.         logx("channel is '%s'", Smtpserver);
  184.     } else {
  185.         log("Channel not specified!");
  186.         log("Usage: smtpd [-d] [-n #connections] smtpserver channel");
  187.         exit(99);
  188.     }
  189. }
  190.  
  191. /* VARARGS */
  192. log( fmt, a, b, c, d )
  193. char *fmt;
  194. {
  195.     fputs( programid, stderr );
  196.     fprintf( stderr, fmt, a, b, c, d );
  197.     fputc( '\n', stderr );
  198.     fflush( stderr );
  199. }
  200.